package com.yeziji.common;

import com.mybatisflex.core.paginate.Page;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页结果
 *
 * @author hwy
 * @since 2023/09/05 2:07
 **/
@Data
@SuperBuilder
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class CommonPage<T> {
    /**
     * 默认分页
     */
    public static final long DEFAULT_PAGE = 0L;

    /**
     * 默认分页数量
     */
    public static final long DEFAULT_COUNT = 10L;

    /**
     * 当前页码, 从 0 开始
     */
    private long pageNumber = DEFAULT_PAGE;

    /**
     * 每页的数量
     */
    private long pageSize = DEFAULT_COUNT;

    /**
     * 数据总数量
     */
    private long total;

    /**
     * 总页数
     */
    private long totalPage;

    /**
     * 数据列表
     */
    private List<T> items;

    /**
     * 空页
     *
     * @param <T> 泛型
     * @return {@link CommonPage} 空数据集合
     */
    public static <T> CommonPage<T> empty() {
        return CommonPage.<T>builder().total(0).items(Collections.emptyList()).build();
    }

    /**
     * 分页转换为返回分页
     *
     * @param page        分页结果
     * @param transformer 转换类型
     * @param <T>         原泛型
     * @param <O>         目标泛型
     * @return {@link CommonPage} 分页结果
     */
    public static <T, O> CommonPage<T> convert(Page<O> page, @Nonnull Function<O, T> transformer) {
        if (page == null) {
            return null;
        }

        return CommonPage.<T>builder()
                .pageNumber(page.getPageNumber())
                .pageSize(page.getPageSize())
                .totalPage(page.getTotalPage())
                .total(page.getTotalRow())
                .items(Optional.ofNullable(page.getRecords())
                        .map(records -> records.stream()
                                .map(transformer)
                                .collect(Collectors.toList()))
                        .orElseGet(ArrayList::new))
                .build();
    }

    /**
     * page 类型转换
     *
     * @param page        原 page 分页结果
     * @param transformer 转换的 function
     * @param <T>         目标泛型
     * @param <O>         原泛型
     * @return {@link Page} 目标结果
     */
    public static <T, O> Page<T> convertOf(Page<O> page, @Nonnull Function<O, T> transformer) {
        if (page == null) {
            return Page.of(1, 10);
        }
        Page<T> tPage = Page.of(page.getPageNumber(), page.getPageSize());
        tPage.setTotalRow(page.getTotalRow());
        tPage.setRecords(Optional.ofNullable(page.getRecords())
                .map(records -> records.stream()
                        .map(transformer)
                        .collect(Collectors.toList()))
                .orElseGet(ArrayList::new));
        return tPage;
    }

    /**
     * 构建分页 page
     *
     * @param page 分页
     * @param <T>  分页泛型
     * @return {@link CommonPage} 分页结果
     */
    public static <T> CommonPage<T> build(Page<T> page) {
        return CommonPage.<T>builder()
                .pageNumber(page.getPageNumber())
                .pageSize(page.getPageSize())
                .totalPage(page.getTotalPage())
                .total(page.getTotalRow())
                .items(Optional.ofNullable(page.getRecords()).orElseGet(ArrayList::new))
                .build();
    }
}
